package com.example.testapp.domain.manager

import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.lifecycle.LiveData
import androidx.work.Constraints
import androidx.work.Data
import androidx.work.NetworkType
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.WorkRequest
import com.example.testapp.data.AppDatabase
import com.example.testapp.data.dao.BalanceDao
import com.example.testapp.data.dao.BalanceImageDao
import com.example.testapp.data.dao.BalanceProcessRecordDao
import com.example.testapp.data.entity.Balance
import com.example.testapp.data.entity.BalanceImage
import com.example.testapp.data.entity.BalanceProcessRecord
import com.example.testapp.domain.util.ImageStorageUtil
import com.example.testapp.domain.util.SnowflakeIdGenerator
import java.io.File
import java.time.LocalDateTime
import java.util.ArrayList
import java.util.concurrent.TimeUnit

/**
 * 账单管理器
 */
class BalanceManager private constructor(private val context: Context) {
    private val database: AppDatabase = AppDatabase.getDatabase(context)
    private val balanceDao: BalanceDao = database.balanceDao()
    private val balanceImageDao: BalanceImageDao = database.balanceImageDao()
    private val processRecordDao: BalanceProcessRecordDao = database.balanceProcessRecordDao()
    private val idGenerator: SnowflakeIdGenerator

    init {
        // 初始化雪花ID生成器（使用设备ID作为唯一标识）
        val deviceId = android.provider.Settings.Secure.getString(
            context.contentResolver, android.provider.Settings.Secure.ANDROID_ID
        )
        val dataCenterId = Math.abs(deviceId.hashCode() % 31) + 1L // 1-31
        val workerId = Math.abs((deviceId + "_worker").hashCode() % 31) + 1L // 1-31
        idGenerator = SnowflakeIdGenerator.getInstance(dataCenterId, workerId)
    }

    /**
     * 创建账单（包含图片）
     * @param imageUri 图片URI
     * @return 创建的账单ID
     */
    fun createBalanceWithImage(imageUri: Uri): Long {
        // 保存图片到临时目录
        val tempImageFile = ImageStorageUtil.saveImageToTemp(context, imageUri)
        if (tempImageFile == null) {
            Log.e(TAG, "Failed to save image to temp directory")
            return -1
        }

        try {
            // 创建账单
            val balanceId = createBalance()
            if (balanceId <= 0) {
                return -1
            }

            // 创建图片记录
            val imageId = addImageToBalance(balanceId, tempImageFile.absolutePath)
            if (imageId <= 0) {
                // 创建图片失败，删除账单
                deleteBalance(balanceId)
                return -1
            }

            // 开始处理流程
            startImageProcessFlow(balanceId, imageId)

            return balanceId
        } catch (e: Exception) {
            Log.e(TAG, "Error creating balance with image", e)
            return -1
        }
    }

    /**
     * 创建账单
     * @return 账单ID
     */
    fun createBalance(): Long {
        val balance = Balance()

        // 设置初始值
        balance.setId(idGenerator.nextId())
        balance.setStatus(Balance.STATUS_PENDING)
        balance.setType(Balance.TYPE_EXPENSE) // 默认为支出
        val now = LocalDateTime.now()
        balance.setCreateDate(now)
        balance.setUpdateDate(now)
        balance.setBillDate(now)
        balance.setDelFlag(0.toByte())

        return balanceDao.insert(balance)
    }

    /**
     * 将图片添加到账单
     * @param balanceId 账单ID
     * @param imagePath 图片路径
     * @return 图片ID
     */
    fun addImageToBalance(balanceId: Long, imagePath: String): Long {
        val image = BalanceImage()

        // 设置初始值
        image.setId(idGenerator.nextId())
        image.setBalanceId(balanceId)
        image.setImagePath(imagePath)
        image.setIsProcessed(false)
        image.setRecognitionStatus(BalanceImage.RECOGNITION_STATUS_PENDING)
        image.setSortOrder(0) // 默认排序顺序
        val now = LocalDateTime.now()
        image.setCreateDate(now)
        image.setUpdateDate(now)
        image.setDelFlag(0.toByte())

        return balanceImageDao.insert(image)
    }

    /**
     * 启动图片处理流程
     * @param balanceId 账单ID
     * @param imageId 图片ID
     */
    fun startImageProcessFlow(balanceId: Long, imageId: Long) {
        // 创建处理记录并启动工作流
        AppDatabase.databaseWriteExecutor.execute {
            try {
                val records = createProcessRecords(balanceId)
                for (record in records) {
                    scheduleProcessTask(balanceId, imageId, record)
                }
            } catch (e: Exception) {
                Log.e(TAG, "Error starting image process flow", e)
            }
        }
    }

    /**
     * 创建处理记录
     * @param balanceId 账单ID
     * @return 处理记录列表
     */
    private fun createProcessRecords(balanceId: Long): List<BalanceProcessRecord> {
        val records = ArrayList<BalanceProcessRecord>()
        val now = LocalDateTime.now()
        val processTypes = intArrayOf(
            BalanceProcessRecord.PROCESS_TYPE_OCR,
            BalanceProcessRecord.PROCESS_TYPE_IMAGE_STORAGE,
            BalanceProcessRecord.PROCESS_TYPE_THUMBNAIL
        )

        for (processType in processTypes) {
            val record = BalanceProcessRecord()
            record.setId(idGenerator.nextId())
            record.setBalanceId(balanceId)
            record.setProcessType(processType)
            record.setStatus(BalanceProcessRecord.STATUS_PENDING)
            record.setRetryCount(0)
            record.setMaxRetryCount(3)
            record.setCreateDate(now)
            record.setUpdateDate(now)
            record.setDelFlag(0.toByte())

            val recordId = processRecordDao.insert(record)
            if (recordId > 0) {
                records.add(record)
            }
        }

        return records
    }

    /**
     * 调度处理任务
     * @param balanceId 账单ID
     * @param imageId 图片ID
     * @param record 处理记录
     */
    private fun scheduleProcessTask(balanceId: Long, imageId: Long, record: BalanceProcessRecord) {
        val inputData = Data.Builder()
            .putLong(BalanceImageProcessWorker.KEY_BALANCE_ID, balanceId)
            .putLong(BalanceImageProcessWorker.KEY_IMAGE_ID, imageId)
            .putLong(BalanceImageProcessWorker.KEY_PROCESS_RECORD_ID, record.getId())
            .putInt(BalanceImageProcessWorker.KEY_PROCESS_TYPE, record.getProcessType() ?: 0)
            .build()

        val constraints = Constraints.Builder()
            .setRequiredNetworkType(NetworkType.CONNECTED)
            .build()

        var initialDelay: Long = 0
        // 图片存储和缩略图生成在OCR之后进行
        if (record.getProcessType() == BalanceProcessRecord.PROCESS_TYPE_IMAGE_STORAGE) {
            initialDelay = 1000 // 1秒后
        } else if (record.getProcessType() == BalanceProcessRecord.PROCESS_TYPE_THUMBNAIL) {
            initialDelay = 2000 // 2秒后
        }

        val workRequest = OneTimeWorkRequest.Builder(BalanceImageProcessWorker::class.java)
            .setInputData(inputData)
            .setConstraints(constraints)
            .setInitialDelay(initialDelay, TimeUnit.MILLISECONDS)
            .build()

        WorkManager.getInstance(context).enqueue(workRequest)
    }

    /**
     * 获取所有账单（LiveData）
     * @return 账单列表LiveData
     */
    fun getAllBalances(): LiveData<List<Balance>> {
        return balanceDao.findAllLive()
    }

    /**
     * 获取账单详情
     * @param balanceId 账单ID
     * @return 账单对象
     */
    fun getBalance(balanceId: Long): Balance? {
        return balanceDao.findById(balanceId)
    }

    /**
     * 获取账单图片
     * @param balanceId 账单ID
     * @return 账单图片列表
     */
    fun getBalanceImages(balanceId: Long): LiveData<List<BalanceImage>> {
        return balanceImageDao.findByBalanceIdLive(balanceId)
    }

    /**
     * 获取账单处理记录
     * @param balanceId 账单ID
     * @return 处理记录列表
     */
    fun getProcessRecords(balanceId: Long): List<BalanceProcessRecord> {
        return processRecordDao.findByBalanceId(balanceId)
    }

    /**
     * 更新账单信息
     * @param balance 账单对象
     */
    fun updateBalance(balance: Balance) {
        balance.setUpdateDate(LocalDateTime.now())
        AppDatabase.databaseWriteExecutor.execute { balanceDao.update(balance) }
    }

    /**
     * 删除账单（物理删除）
     * @param balanceId 账单ID
     */
    fun deleteBalance(balanceId: Long) {
        AppDatabase.databaseWriteExecutor.execute {
            val balance = balanceDao.findById(balanceId)
            if (balance != null) {
                balanceDao.delete(balance)
            }
        }
    }

    /**
     * 软删除账单
     * @param balanceId 账单ID
     */
    fun softDeleteBalance(balanceId: Long) {
        AppDatabase.databaseWriteExecutor.execute {
            val now = LocalDateTime.now()
            balanceDao.softDelete(balanceId, now)
            balanceImageDao.softDeleteByBalanceId(balanceId, now)
            processRecordDao.softDeleteByBalanceId(balanceId, now)
        }
    }

    /**
     * 恢复已软删除的账单
     * @param balanceId 账单ID
     */
    fun restoreBalance(balanceId: Long) {
        AppDatabase.databaseWriteExecutor.execute {
            val now = LocalDateTime.now()
            balanceDao.restore(balanceId, now)
        }
    }

    /**
     * 重试失败的处理
     * @param recordId 处理记录ID
     */
    fun retryProcess(recordId: Long) {
        AppDatabase.databaseWriteExecutor.execute {
            val record = processRecordDao.findById(recordId)
            if (record == null || record.getStatus() != BalanceProcessRecord.STATUS_FAILED) {
                return@execute
            }

            // 更新状态为待处理
            val now = LocalDateTime.now()
            processRecordDao.updateStatus(recordId, BalanceProcessRecord.STATUS_PENDING, now)

            // 获取关联的账单和图片
            val balance = balanceDao.findById(record.getBalanceId() ?: return@execute)
                ?: return@execute

            val images = balanceImageDao.findByBalanceId(record.getBalanceId() ?: return@execute)
            if (images.isEmpty()) {
                return@execute
            }

            // 重新调度任务
            val image = images[0] // 取第一张图片
            scheduleProcessTask(balance.getId(), image.getId(), record)
        }
    }

    /**
     * 清理临时文件
     */
    fun cleanupTempFiles() {
        AppDatabase.databaseWriteExecutor.execute {
            ImageStorageUtil.cleanupTempFiles(context)
        }
    }

    companion object {
        private const val TAG = "BalanceManager"

        // 单例实例
        @Volatile
        private var INSTANCE: BalanceManager? = null

        /**
         * 获取实例
         * @param context 上下文
         * @return BalanceManager实例
         */
        fun getInstance(context: Context): BalanceManager {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: BalanceManager(context.applicationContext).also { INSTANCE = it }
            }
        }
    }
} 